
#import "SimPageScrollView.h"

NSString * const kSimPageScrollViewWillDisappearPageNoti = @"kSimPageScrollViewWillDisappearPageNoti";

@interface SimPageScrollView () <UIScrollViewDelegate>
{
}

@end

@implementation SimPageScrollView {
    NSInteger _minPageIndex;
    NSInteger _maxPageIndex;
    NSMutableArray *_delayLoadPages;
    
    BOOL   _innerEndScroll;
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        self.delegate = self;
        [self setPagingEnabled:YES];
        [self setBounces:NO];
        [self setShowsHorizontalScrollIndicator:NO];
        [self setShowsVerticalScrollIndicator:NO];
        [self setDirectionalLockEnabled:YES];
        _numberOfReusableViews = 3;
        
        _availablePages = [NSMutableDictionary dictionary];
        _delayLoadPages = [NSMutableArray array];
        _currentPageIndex = NSNotFound;
    }
    return self;
}

- (void)setFrame:(CGRect)frame
{
    [super setFrame:frame];
    
    if (_currentPageIndex != NSNotFound && !CGRectIsEmpty(frame)) {
        [self setupScrollViewForDisplayingPage:_currentPageIndex];
    }
}

- (void)willMoveToWindow:(UIWindow *)newWindow
{
    if (newWindow != nil) {
        if (_currentPageIndex == NSNotFound) {
            [self displayPage:0 animated:NO];
        }
    }
}


#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if ([_pageDelegate respondsToSelector:@selector(pageScrollViewDidScroll:)]) {
        [_pageDelegate pageScrollViewDidScroll:self];
    }
}

- (void)scrollViewEndScroll:(UIScrollView *)scrollView
{
    _innerEndScroll = NO;
    self.userInteractionEnabled = YES;
    NSInteger currentPage = 0;
    if (_isVerticalScroll) {
        currentPage = nearbyintf(scrollView.contentOffset.y / scrollView.frame.size.height) + _minPageIndex;
    }
    else{
        currentPage = nearbyintf(scrollView.contentOffset.x / scrollView.frame.size.width) + _minPageIndex;
    }
    
    BOOL pageChanged = (_currentPageIndex != currentPage);
    if (pageChanged) {
        if (_currentPageIndex != NSNotFound) {
            [[NSNotificationCenter defaultCenter] postNotificationName:kSimPageScrollViewWillDisappearPageNoti object:self];
            if([_pageDelegate respondsToSelector:@selector(pageScrollView:didDisappearPage:)]){
                [_pageDelegate pageScrollView:self didDisappearPage:_currentPageIndex];
            }
        }
        _currentPageIndex = currentPage;
        [self setupScrollViewForDisplayingPage:currentPage];
        
        if([_pageDelegate respondsToSelector:@selector(pageScrollView:didShowPage:)]){
            [_pageDelegate pageScrollView:self didShowPage:currentPage];
        }
    }
    else{
        [self setupScrollViewForDisplayingPage:currentPage];
    }
    
    
    if([_pageDelegate respondsToSelector:@selector(pageScrollViewEndScroll:)]){
        [_pageDelegate pageScrollViewEndScroll:self];
    }
}

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
    if (_innerEndScroll) {
        //系统自动触发sroll中断
        return;
    }
    [self scrollViewEndScroll:scrollView];
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [self scrollViewEndScroll:scrollView];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
{
    if (!decelerate) {
        [self scrollViewEndScroll:scrollView];
    }
}

- (void)clearAllPageView
{
    for ( NSNumber *pageIndex in _availablePages.allKeys ){
        [self clearPageAtIndex:pageIndex];
    }
    _currentPageIndex = NSNotFound;
}

- (void)clearPageAtIndex:(NSNumber *)pageIndex
{
    if (_availablePages[pageIndex] == nil) {
        return;
    }
    
    if([_pageDelegate respondsToSelector:@selector(pageScrollView:willRemoveView:atPage:)])
        [_pageDelegate pageScrollView:self
                       willRemoveView:_availablePages[pageIndex]
                               atPage:[pageIndex integerValue]];
    
    [_availablePages[pageIndex] removeFromSuperview];
    [_availablePages removeObjectForKey:pageIndex];
    
    if([_pageDelegate respondsToSelector:@selector(pageScrollView:didRemoveViewAtPage:)])
        [_pageDelegate pageScrollView:self
                  didRemoveViewAtPage:[pageIndex integerValue]];
}

- (void)deletePageAtIndex:(NSInteger)pageIndex
{    
    [self clearPageAtIndex:@(pageIndex)];
    for (NSInteger i = pageIndex+1; i <= _maxPageIndex; i++) {
        _availablePages[@(i-1)] = _availablePages[@(i)];
    }
    _availablePages[@(_maxPageIndex)] = nil;
     
    NSInteger numberOfPages = [_dataSource numberOfPagesForPageScrollView:self];
    _currentPageIndex = MIN(pageIndex, numberOfPages-1);
    [self setupScrollViewForDisplayingPage:_currentPageIndex];
}

#pragma mark - Private methods
- (void)cancelDelayLoadBesideView
{
    [_delayLoadPages removeAllObjects];
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(delayLoadPages) object:nil];
    
}

- (void)displayPage:(NSInteger)pageIndex animated:(BOOL)animated
{
    if (_isVerticalScroll) {
        CGFloat offset = floor(self.frame.size.height * (pageIndex - _minPageIndex));
        if (offset == self.contentOffset.y) {
            [self scrollViewEndScroll:self];
        }
        else{
            self.userInteractionEnabled = NO;
            //修复系统setContentOffset, animate为NO 调用scrollViewDidEndScrollingAnimation的Bug
            _innerEndScroll = animated ? NO : YES;
            [self setContentOffset:CGPointMake(0, offset) animated:animated];
            _innerEndScroll = NO;
            if (!animated) {
                [self scrollViewEndScroll:self];
            }
        }
    }
    else{
        CGFloat offset = floor(self.frame.size.width * (pageIndex - _minPageIndex));
        if (offset == self.contentOffset.x) {
            [self scrollViewEndScroll:self];
        }
        else{
            self.userInteractionEnabled = NO;
            //修复系统setContentOffset, animate为NO 调用scrollViewDidEndScrollingAnimation的Bug
            _innerEndScroll = animated ? NO : YES; //修复系统setContentOffset调用scrollViewDidEndScrollingAnimation的Bug
            [self setContentOffset:CGPointMake(offset, 0) animated:animated];
            _innerEndScroll = NO;
            if (!animated) {
                [self scrollViewEndScroll:self];
            }
        }
    }
}

- (void)setupScrollViewForDisplayingPage:(NSInteger)pageIndex
{
    [self cancelDelayLoadBesideView];
    
    NSInteger numberOfPages = [_dataSource numberOfPagesForPageScrollView:self];
    if(numberOfPages < _numberOfReusableViews){
        _numberOfReusableViews = numberOfPages;
    }
    
    NSInteger prePage = MAX(1, (_numberOfReusableViews - 1) / 2.0f);
    NSInteger nextPage = MAX(1, (_numberOfReusableViews - 1) - prePage);
    _minPageIndex = MAX(0, pageIndex - prePage);
    _maxPageIndex = MIN(numberOfPages-1, pageIndex + nextPage);
    
    // remove unused views
    for ( NSNumber *pageIndex in _availablePages.allKeys )
    {
        if ( pageIndex.integerValue < _minPageIndex || pageIndex.integerValue > _maxPageIndex)
        {
            [self clearPageAtIndex:pageIndex];
            
            [_availablePages[pageIndex] removeFromSuperview];
            [_availablePages removeObjectForKey:pageIndex];
            
            if([_pageDelegate respondsToSelector:@selector(pageScrollView:didRemoveViewAtPage:)])
                [_pageDelegate pageScrollView:self
                          didRemoveViewAtPage:pageIndex.integerValue];
        }
    }
    
    // add in new views
    for ( NSInteger i = _minPageIndex; i <= _maxPageIndex; i++ ){
        UIView *viewForPage = _availablePages[@(i)];
        if (viewForPage == nil) {
            if (i == pageIndex) {
                [self loadViewAtIndex:i];
            }
            else{
                [_delayLoadPages addObject:@(i)];
            }
        }
        else{
            [self updatePositionAtIdnex:i];
        }
    }
    
    if (_delayLoadPages.count > 0) {
        [self performSelector:@selector(delayLoadPages) withObject:nil afterDelay:0.01];
    }
    
    if (_isVerticalScroll) {
        [self setContentOffset:CGPointMake(0, self.frame.size.height * (pageIndex - _minPageIndex))];
        self.contentSize = CGSizeMake(self.frame.size.width, self.frame.size.height * (_maxPageIndex - _minPageIndex + 1));
    }
    else{
        [self setContentOffset:CGPointMake(self.frame.size.width * (pageIndex - _minPageIndex), 0)];
        self.contentSize = CGSizeMake(self.frame.size.width * (_maxPageIndex - _minPageIndex + 1), self.frame.size.height);
    }
}

- (void)delayLoadPages
{
    for (NSNumber *pageNum in _delayLoadPages){
        [self loadViewAtIndex:[pageNum integerValue]];
    }
}

- (void)loadViewAtIndex:(NSInteger)index
{
    if (self.dataSource == nil) {
        return;
    }
    
    UIView *viewForPage = _availablePages[@(index)];
    if (viewForPage == nil){
        viewForPage = [self.dataSource viewForScrollView:self page:index];
        if (viewForPage) {
            [self addSubview:viewForPage];
            [_availablePages setObject:viewForPage forKey:@(index)];
        }
    }
    
    [self updatePositionAtIdnex:index];
}

- (void)updatePositionAtIdnex:(NSInteger)index
{
    UIView *view = _availablePages[@(index)];
    if (view) {
        if (_isVerticalScroll) {
            view.frame = CGRectMake(0, (index - _minPageIndex) * self.frame.size.height, self.frame.size.width, view.frame.size.height);
        }
        else{
            view.frame = CGRectMake((index - _minPageIndex) * self.frame.size.width, 0, view.frame.size.width, self.frame.size.height);
        }
    }
}

- (UIView *)curPageView
{
    return _availablePages[@(_currentPageIndex)];
}

- (id)viewForPage:(NSInteger)page
{
    return _availablePages[@(page)];
}



@end
